import { Formation } from './Formation';
import { General } from './General';
import { TroopType, DamageType, FormationType } from '../types';

export class Battle {
  private readonly MAX_TURNS = 8;
  private readonly TROOP_COUNTER: Record<TroopType, TroopType> = {
    [TroopType.CAVALRY]: TroopType.SHIELD,
    [TroopType.SHIELD]: TroopType.ARCHER,
    [TroopType.ARCHER]: TroopType.SPEAR,
    [TroopType.SPEAR]: TroopType.CAVALRY
  };
  private currentTurn = 1;
  private battleLog: any[] = [];

  constructor(
    private teamA: General[],
    private teamB: General[],
    private formationA: Formation,
    private formationB: Formation
  ) {}

  start(): void {
    while (this.currentTurn <= this.MAX_TURNS && !this.isGameOver()) {
      this.executeTurn();
    }
  }

  private executeTurn(): void {
    const allGenerals = [...this.teamA, ...this.teamB]
      .filter(general => general.isAlive())
      .sort((a, b) => b.attributes.initiative - a.attributes.initiative);

    for (const general of allGenerals) {
      if (general.isAlive()) {
        general.executeAction(this);
      }
    }

    this.currentTurn++;
    this.updateEffects();
  }

  calculateDamage(
    source: General,
    target: General,
    damageType: DamageType
  ): number {
    let baseDamage = 0;

    // 计算基础伤害
    if (damageType === DamageType.Physical) {
      baseDamage = this.calculatePhysicalDamage(source, target);
    } else {
      baseDamage = this.calculateStrategyDamage(source, target);
    }

    // 应用源角色的增伤效果
    baseDamage = source.calculateOutgoingDamage(baseDamage, damageType);

    // 应用目标的减伤效果
    baseDamage = target.receiveDamage(baseDamage);

    return Math.floor(baseDamage);
  }

  selectTarget(source: General): General | null {
    const enemyTeam = this.teamA.includes(source) ? this.teamB : this.teamA;
    const aliveEnemies = enemyTeam.filter(g => g.isAlive());
    
    if (aliveEnemies.length === 0) return null;

    const enemyFormation = this.getGeneralFormation(aliveEnemies[0]);
    if (!enemyFormation) return aliveEnemies[0];

    // 根据阵型概率选择目标
    const totalWeight = aliveEnemies.reduce((sum, enemy) => {
      const effect = enemyFormation.getFormationEffect(enemy.position);
      return sum + effect.targetProbability;
    }, 0);

    let random = Math.random() * totalWeight;
    
    for (const enemy of aliveEnemies) {
      const effect = enemyFormation.getFormationEffect(enemy.position);
      random -= effect.targetProbability;
      if (random <= 0) return enemy;
    }

    return aliveEnemies[0];
  }

  private calculatePhysicalDamage(source: General, target: General): number {
    const baseDamage = source.attributes.power;
    const reduction = target.attributes.leadership / 200;
    return baseDamage * (1 - reduction);
  }

  private calculateStrategyDamage(source: General, target: General): number {
    const baseDamage = source.attributes.intelligence;
    const reduction = (target.attributes.intelligence + target.attributes.leadership) / 400;
    return baseDamage * (1 - reduction);
  }

  private getTroopTypeBonus(attackerType: TroopType, defenderType: TroopType): number {
    return this.TROOP_COUNTER[attackerType] === defenderType ? 1.5 : 1;
  }

  private getGeneralFormation(general: General): Formation {
    return this.teamA.includes(general) ? this.formationA : this.formationB;
  }

  private updateEffects(): void {
    [...this.teamA, ...this.teamB].forEach(general => {
      if (general.isAlive()) {
        general.updateEffects();
        general.skills.forEach(skill => skill.updateCooldown());
      }
    });
  }

  private isGameOver(): boolean {
    const teamAAlive = this.teamA.some(general => general.isAlive());
    const teamBAlive = this.teamB.some(general => general.isAlive());
    return !teamAAlive || !teamBAlive;
  }

  getAllies(general: General): General[] {
    // 判断该武将属于哪个队伍
    const team = this.teamA.includes(general) ? this.teamA : this.teamB;
    
    // 返回同一队伍中存活的武将
    return team.filter(ally => ally.isAlive());
  }

  getEnemies(general: General): General[] {
    // 判断该武将属于哪个队伍，返回敌方队伍
    const enemyTeam = this.teamA.includes(general) ? this.teamB : this.teamA;
    
    // 返回敌方队伍中存活的武将
    return enemyTeam.filter(enemy => enemy.isAlive());
  }

  getRandomEnemy(source: General): General | null {
    const enemies = this.getEnemies(source);
    if (enemies.length === 0) return null;
    
    // 随机选择一个敌方武将
    const randomIndex = Math.floor(Math.random() * enemies.length);
    return enemies[randomIndex];
  }

  getResult() {
    if (this.currentTurn > this.MAX_TURNS) {
      return {
        status: 'draw',
        remainingTroops: {
          teamA: this.teamA.map(g => ({ id: g.id, troops: g.troops })),
          teamB: this.teamB.map(g => ({ id: g.id, troops: g.troops }))
        }
      };
    }

    const teamAAlive = this.teamA.some(g => g.isAlive());
    const teamBAlive = this.teamB.some(g => g.isAlive());

    if (!teamBAlive) return { status: 'teamA_win' };
    if (!teamAAlive) return { status: 'teamB_win' };
    
    return { status: 'ongoing' };
  }
}
